import java.util.Arrays;

/** A class used to store informations about computed states in checker.<br>
 *  The point of this class is to have a faster access to informations about computed states.<br>
 *  Also, it allows to store computed informations using significantly less memory, than storing them as Board objects.<br>
 *  This implementation overrides equals and hashCode methods.
 *  
 *  @author crezax
 */

public class BoardState {
	private Position p[], b[];
	private Direction dir;
	
	/**
     * Constructor that creates BoardState out of a given Board
     */
	public BoardState(Board board){
		p = new Position[board.getPlayers().length];
		b = new Position[board.getBoxes().length];
		for (int i = 0; i<p.length; i++){
			p[i] = new Position(board.getPlayers()[i].getPosition());
		}
		for (int i = 0; i<b.length; i++){
			b[i] = new Position(board.getBoxes()[i].getPosition());
		}
	}
	
	/**
     * Copy constructor.
     */
	public BoardState(BoardState bS){
		p = bS.getPlayers();
		b = bS.getBoxes();
		dir = bS.dir;
	}
	
	/**
     * A method, that returns an array of players' positions.
     *
     * @return an array containing positions of all players on Board State
     */
	public Position[] getPlayers(){
		return Arrays.copyOf(p, p.length);
	}
	
	/**
     * A method, that returns an array of boxes' positions.
     *
     * @return an array containing positions of all boxes on Board State
     */
	public Position[] getBoxes(){
		return Arrays.copyOf(b, b.length);
	}
	
	/**
	 * Method, that overrides hashCode method inherited from Object class.<br>
	 * It is guaranteed, that it returns the same hash for any two BoardState objects that are equal according to equals method implemented in this class.
	 */
	@Override
	public int hashCode(){
		if (this == null) return 0;
		int hc = 1;
		for (Position player : p){
			hc+=(6423*player.x+1)+5346*(player.y+1);
		}
		for (Position box : b){
			hc+=(8281*box.x+1)+9102*(box.y+1);
		}
		return hc;
	}
	
	/**
	 * Method, that overrides equals method inherited from Object class.<br>
	 * 
	 * @return true if compared object is BoardState instance and if both objects contain the same set of positions for both boxes and players.<br>
	 * Please note, that this method doesn't compare any players' or boxes' fields except their positions.<br>
	 * Returns false otherwise.  
	 */
	@Override
	public boolean equals(Object o){
		if (!(o instanceof BoardState)) return false;
		BoardState bS = (BoardState) o;
		for (Position player1 : p){
			boolean found = false;
			for (Position player2 : bS.p)
				if (player1.equals(player2)){
					found = true;
					break;
				}
			if (found == false) return false;
		}
		for (Position box1 : b){
			boolean found = false;
			for (Position box2 : bS.b)
				if (box1.equals(box2)){
					found = true;
					break;
				}
			if (found == false) return false;
		}
		return true;
	}
	
	/**
	 * Method, that overrides toString method inherited from Object class.<br>
	 * 
	 * @return List of positions of players and list of positions of boxes, both separated with 5 spaces.
	 */
	@Override
	public String toString(){
		StringBuffer sB = new StringBuffer();
		for (Position pos : p) sB.append(pos + " ");
		sB.append("     ");
		for (Position pos : b) sB.append(pos + " ");
		return sB.toString();
	}
}
